home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / plug-ins / perl / Gimp / Lib.xs < prev    next >
Encoding:
Text File  |  2003-05-20  |  58.7 KB  |  2,326 lines

  1. #include "config.h"
  2.  
  3. #include <assert.h>
  4. #include <stdio.h>
  5.  
  6. #include <libgimp/gimp.h>
  7.  
  8. #if GIMP_MAJOR_VERSION>1 || (GIMP_MAJOR_VERSION==1 && GIMP_MINOR_VERSION>=1)
  9. # define GIMP11 1
  10. # define GIMP_PARASITE 1
  11. #endif
  12.  
  13. /* FIXME */
  14. /* sys/param.h is redefining these! */
  15. #undef MIN
  16. #undef MAX
  17.  
  18. #if HAVE_PDL
  19. #define PDL_clean_namespace
  20. #include <pdlcore.h>
  21. #endif
  22.  
  23. /* various functions allocate static buffers, STILL.  */
  24. #define MAX_STRING 4096
  25.  
  26. /* dunno where this comes from */
  27. #undef VOIDUSED
  28.  
  29. #include "EXTERN.h"
  30. #include "perl.h"
  31. #include "XSUB.h"
  32. #include "gppport.h"
  33.  
  34. #ifndef pTHX_
  35. #define pTHX_
  36. #endif
  37.  
  38. #include "../perl-intl.h"
  39.  
  40. /* dirty is used in gimp.h AND in perl < 5.005 or with PERL_POLLUTE.  */
  41. #ifdef dirty
  42. # undef dirty
  43. #endif
  44.  
  45. #include "extradefs.h"
  46.  
  47. #define GIMP_PKG    "Gimp::"    /* the package name */
  48.  
  49. #define PKG_COLOR    GIMP_PKG "Color"
  50. #define PKG_REGION    GIMP_PKG "Region"
  51. #define PKG_DISPLAY    GIMP_PKG "Display"
  52. #define PKG_IMAGE    GIMP_PKG "Image"
  53. #define PKG_LAYER    GIMP_PKG "Layer"
  54. #define PKG_CHANNEL    GIMP_PKG "Channel"
  55. #define PKG_DRAWABLE    GIMP_PKG "Drawable"
  56. #define PKG_SELECTION    GIMP_PKG "Selection"
  57. #define PKG_REGION    GIMP_PKG "Region"
  58. #if GIMP_PARASITE
  59. # define PKG_PARASITE    GIMP_PKG "Parasite"
  60. #else
  61. # define PKG_PARASITE    ((char *)0)
  62. #endif
  63.  
  64. #define PKG_GDRAWABLE    GIMP_PKG "GimpDrawable"
  65. #define PKG_TILE    GIMP_PKG "Tile"
  66. #define PKG_PIXELRGN    GIMP_PKG "PixelRgn"
  67.  
  68. #define PKG_ANY        ((char *)0)
  69.  
  70. static char pkg_anyable[] = PKG_DRAWABLE ", " PKG_LAYER " or " PKG_CHANNEL;
  71. #define PKG_ANYABLE    (pkg_anyable)
  72.  
  73. static int trace = TRACE_NONE;
  74.  
  75. #if HAVE_PDL
  76.  
  77. typedef GimpPixelRgn GimpPixelRgn_PDL;
  78.  
  79. /* hack, undocumented, argh! */
  80. static Core* PDL; /* Structure hold core C functions */
  81.  
  82. /* get pointer to PDL structure. */
  83. static void need_pdl (void)
  84. {
  85.   SV *CoreSV;
  86.  
  87.   if (!PDL)
  88.     {
  89.       /* the perl-server can't be bothered to do this itself! */
  90.       perl_require_pv ("PDL::Core");
  91.  
  92.       /* Get pointer to structure of core shared C routines */
  93.       CoreSV = perl_get_sv("PDL::SHARE", FALSE);
  94.       if (!CoreSV)
  95.         croak("gimp-perl-pixel functions require the PDL::Core module, which was not found");
  96.  
  97.       PDL = (Core*) SvIV(CoreSV);
  98.     }
  99. }
  100.  
  101. static pdl *new_pdl (int a, int b, int c)
  102. {
  103.   pdl *p = PDL->new();
  104.   PDL_Long dims[3];
  105.   int ndims = 0;
  106.  
  107.   if (c > 0) dims[ndims++] = c;
  108.   if (b > 0) dims[ndims++] = b;
  109.   if (a > 0) dims[ndims++] = a;
  110.  
  111.   PDL->setdims (p, dims, ndims);
  112.   p->datatype = PDL_B;
  113.   PDL->allocdata (p);
  114.  
  115.   return p;
  116. }
  117.  
  118. static void old_pdl (pdl **p, short ndims, int dim0)
  119. {
  120.   PDL->make_physical (*p);
  121.   PDL->converttype (p, PDL_B, PDL_PERM);
  122.  
  123.   if ((*p)->ndims < ndims + (dim0 > 1))
  124.     croak (__("dimension mismatch, pdl has dimension %d but at least %d dimensions required"), (*p)->ndims, ndims + (dim0 > 1));
  125.  
  126.   if ((*p)->ndims > ndims + 1)
  127.     croak (__("dimension mismatch, pdl has dimension %d but at most %d dimensions allowed"), (*p)->ndims, ndims + 1);
  128.  
  129.   if ((*p)->ndims > ndims && (*p)->dims[0] != dim0)
  130.     croak (__("pixel size mismatch, pdl has %d channel pixels but %d channels are required"), (*p)->dims[0], dim0);
  131. }
  132.  
  133. static void pixel_rgn_pdl_delete_data (pdl *p, int param)
  134. {
  135.   p->data = 0;
  136. }
  137.  
  138. /* please optimize! */
  139. static pdl *redim_pdl (pdl *p, int ndim, int newsize)
  140. {
  141.   pdl *r = PDL->null ();
  142.   AV *dims, *dimincs;
  143.   int i;
  144.  
  145.   dims    = newAV ();
  146.   dimincs = newAV ();
  147.  
  148.   for (i = 0; i < p->ndims; i++)
  149.     {
  150.       av_push (dims   , newSViv (p->dims   [i]));
  151.       av_push (dimincs, newSViv (p->dimincs[i]));
  152.     }
  153.  
  154.   sv_setiv (*av_fetch (dims, ndim, 0), newsize);
  155.  
  156.   PDL->affine_new (p, r, 0, 
  157.                    sv_2mortal (newRV_noinc ((SV*)dims)),
  158.                    sv_2mortal (newRV_noinc ((SV*)dimincs)));
  159.  
  160.   return r;
  161. }
  162.  
  163. #endif
  164.  
  165. /* set when its safe to call gimp functions.  */
  166. static int gimp_is_initialized = 0;
  167.  
  168. typedef gint32 IMAGE;
  169. typedef gint32 LAYER;
  170. typedef gint32 CHANNEL;
  171. typedef gint32 DRAWABLE;
  172. typedef gint32 SELECTION;
  173. typedef gint32 DISPLAY;
  174. typedef gint32 REGION;
  175. typedef gint32 COLOR;
  176. typedef gpointer GimpPixelRgnIterator;
  177.  
  178. /* new SV with len len.  There _must_ be a better way, but newSV doesn't work.  */
  179. static SV *newSVn (STRLEN len)
  180. {
  181.   SV *sv = newSVpv ("", 0);
  182.   
  183.   (void) SvUPGRADE (sv, SVt_PV);
  184.   SvGROW (sv, len);
  185.   SvCUR_set (sv, len);
  186.   
  187.   return sv;
  188. }
  189.  
  190. static GHashTable *gdrawable_cache;
  191.  
  192. /* magic stuff.  literally.  */
  193. static int gdrawable_free (pTHX_ SV *obj, MAGIC *mg)
  194. {
  195.   GimpDrawable *gdr = (GimpDrawable *)SvIV(obj);
  196.  
  197.   g_hash_table_remove (gdrawable_cache, (gpointer)gdr->id);
  198.   gimp_drawable_detach (gdr);
  199.  
  200.   return 0;
  201. }
  202.  
  203. static MGVTBL vtbl_gdrawable = {0, 0, 0, 0, gdrawable_free};
  204.  
  205. static SV *new_gdrawable (gint32 id)
  206. {
  207.    static HV *stash;
  208.    SV *sv;
  209.    
  210.    if (!gdrawable_cache)
  211.      gdrawable_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
  212.  
  213.    assert (sizeof (gpointer) >= sizeof (id));
  214.  
  215.    if ((sv = (SV*)g_hash_table_lookup (gdrawable_cache, (gpointer)id)))
  216.      SvREFCNT_inc (sv);
  217.    else
  218.      {
  219.        GimpDrawable *gdr = gimp_drawable_get (id);
  220.  
  221.        if (!gdr)
  222.          croak (__("unable to convert Gimp::Drawable into Gimp::GimpDrawable (id %d)"), id);
  223.  
  224.        if (!stash)
  225.          stash = gv_stashpv (PKG_GDRAWABLE, 1);
  226.  
  227.        sv = newSViv ((IV) gdr);
  228.        sv_magic (sv, 0, '~', 0, 0);
  229.        mg_find (sv, '~')->mg_virtual = &vtbl_gdrawable;
  230.  
  231.        g_hash_table_insert (gdrawable_cache, (gpointer)id, (void *)sv);
  232.      }
  233.    
  234.    return sv_bless (newRV_noinc (sv), stash);
  235. }
  236.  
  237. static GimpDrawable *old_gdrawable (SV *sv)
  238. {
  239.   if (!(sv_derived_from (sv, PKG_GDRAWABLE)))
  240.     croak (__("argument is not of type %s"), PKG_GDRAWABLE);
  241.  
  242.   /* the next line lacks any type of checking.  */
  243.   return (GimpDrawable *)SvIV(SvRV(sv));
  244. }
  245.  
  246. static /* drawable/tile/region stuff.  */
  247. SV *new_tile (GimpTile *tile, SV *gdrawable)
  248. {
  249.   static HV *stash;
  250.   HV *hv = newHV ();
  251.   
  252.   hv_store (hv, "_gdrawable"    ,10, SvREFCNT_inc (gdrawable)    , 0);
  253.   
  254.   if (!stash)
  255.     stash = gv_stashpv (PKG_TILE, 1);
  256.   
  257.   return sv_bless (newRV_noinc ((SV*)hv), stash);
  258. }
  259.  
  260. static GimpTile *old_tile (SV *sv)
  261. {
  262.   if (!sv_derived_from (sv, PKG_TILE))
  263.     croak (__("argument is not of type %s"), PKG_TILE);
  264.   
  265.   /* the next line lacks any type of checking.  */
  266.   return (GimpTile *)SvIV(*(hv_fetch ((HV*)SvRV(sv), "_tile", 5, 0)));
  267. }
  268.  
  269. /* magic stuff.  literally.  */
  270. static int gpixelrgn_free (pTHX_ SV *obj, MAGIC *mg)
  271. {
  272. /*  GimpPixelRgn *pr = (GimpPixelRgn *)SvPV_nolen(obj); */
  273. /* automatically done on detach */
  274. /*  if (pr->dirty)
  275.      gimp_drawable_flush (pr->drawable);*/
  276.  
  277.   return 0;
  278. }
  279.  
  280. static MGVTBL vtbl_gpixelrgn = {0, 0, 0, 0, gpixelrgn_free};
  281.  
  282. /* coerce whatever was given into a gdrawable-sv */
  283. static SV *force_gdrawable (SV *drawable)
  284. {
  285.   if (!(sv_derived_from (drawable, PKG_GDRAWABLE)))
  286.     {
  287.       if (sv_derived_from (drawable, PKG_DRAWABLE)
  288.           || sv_derived_from (drawable, PKG_LAYER)
  289.           || sv_derived_from (drawable, PKG_CHANNEL))
  290.         drawable = sv_2mortal (new_gdrawable (SvIV (SvRV (drawable))));
  291.       else
  292.         croak (__("argument is not of type %s"), PKG_GDRAWABLE);
  293.     }
  294.  
  295.   return drawable;
  296. }
  297.  
  298. static SV *new_gpixelrgn (SV *gdrawable, int x, int y, int width, int height, int dirty, int shadow)
  299. {
  300.   static HV *stash;
  301.   SV *sv = newSVn (sizeof (GimpPixelRgn));
  302.   GimpPixelRgn *pr = (GimpPixelRgn *)SvPV_nolen(sv);
  303.  
  304.   if (!stash)
  305.     stash = gv_stashpv (PKG_PIXELRGN, 1);
  306.   
  307.   gimp_pixel_rgn_init (pr, old_gdrawable (gdrawable),
  308.                        x, y, width, height, dirty, shadow);
  309.  
  310.   sv_magic (sv, SvRV(gdrawable), '~', 0, 0);
  311.   mg_find (sv, '~')->mg_virtual = &vtbl_gpixelrgn;
  312.  
  313.   return sv_bless (newRV_noinc (sv), stash);
  314. }
  315.  
  316. static GimpPixelRgn *old_pixelrgn (SV *sv)
  317. {
  318.   if (!sv_derived_from (sv, PKG_PIXELRGN))
  319.     croak (__("argument is not of type %s"), PKG_PIXELRGN);
  320.   
  321.   return (GimpPixelRgn *)SvPV_nolen(SvRV(sv));
  322. }
  323.  
  324. static GimpPixelRgn *old_pixelrgn_pdl (SV *sv)
  325. {
  326. #if HAVE_PDL
  327.   need_pdl ();
  328. #endif
  329.   return old_pixelrgn (sv);
  330. }
  331.  
  332. /* tracing stuff.  */
  333. static SV *trace_var = 0;
  334. static PerlIO *trace_file = 0; /* FIXME: unportable.  */
  335.  
  336. static void
  337. trace_init ()
  338. {
  339.   if (!trace_file)
  340.     SvCUR_set (trace_var, 0);
  341. }
  342.  
  343. #ifndef __STDC__
  344. #error You need to compile with an ansi-c compiler!!!
  345. #error Remove these lines to continue at your own risk!
  346. #endif
  347.  
  348. #if __STDC_VERSION__ > 199900
  349. #define trace_printf(...) \
  350.     do { \
  351.             if (trace_file) PerlIO_printf (trace_file, __VA_ARGS__); \
  352.         else        sv_catpvf (trace_var, __VA_ARGS__); \
  353.         } while(0)
  354. #elif __GNUC__
  355. #define trace_printf(frmt,args...) \
  356.         do { \
  357.         if (trace_file) PerlIO_printf (trace_file, frmt, ## args); \
  358.         else        sv_catpvf (trace_var, frmt, ## args); \
  359.         } while(0)
  360. #elif defined(__STDC__)
  361.  
  362. /* sigh */
  363. #include <stdarg.h>
  364. static void trace_printf (char *frmt, ...)
  365. {
  366.   va_list args;
  367.   char buffer[MAX_STRING]; /* sorry... */
  368.   
  369.   va_start (args, frmt);
  370. #ifdef HAVE_VSNPRINTF
  371.   vsnprintf (buffer, sizeof buffer, frmt, args);
  372. #else
  373.   vsprintf (buffer, frmt, args);
  374. #endif
  375.   if (trace_file) PerlIO_printf (trace_file, "%s", buffer);
  376.   else          sv_catpv (trace_var, buffer);
  377. }
  378.  
  379. #endif
  380.  
  381. static int
  382. is_array (GimpPDBArgType typ)
  383. {
  384.   return typ == GIMP_PDB_INT32ARRAY
  385.       || typ == GIMP_PDB_INT16ARRAY
  386.       || typ == GIMP_PDB_INT8ARRAY
  387.       || typ == GIMP_PDB_FLOATARRAY
  388.       || typ == GIMP_PDB_STRINGARRAY;
  389. }
  390.  
  391. static int
  392. perl_param_count (GimpParam *arg, int count)
  393. {
  394.   GimpParam *end = arg + count;
  395.   
  396.   while (arg < end)
  397.     if (is_array (arg++->type))
  398.       count--;
  399.   
  400.   return count;
  401. }
  402.  
  403. /*
  404.  * count actual parameter number
  405.  */
  406. static int
  407. perl_paramdef_count (GimpParamDef *arg, int count)
  408. {
  409.   GimpParamDef *end = arg + count;
  410.   
  411.   while (arg < end)
  412.     if (is_array (arg++->type))
  413.       count--;
  414.   
  415.   return count;
  416. }
  417.  
  418. /* horrors!  c wasn't designed for this!  */
  419. #define dump_printarray(args,index,ctype,datatype,frmt) {\
  420.   int j; \
  421.   trace_printf ("["); \
  422.   if (args[index].data.datatype || !args[index-1].data.d_int32) \
  423.     { \
  424.       for (j = 0; j < args[index-1].data.d_int32; j++) \
  425.     trace_printf (frmt "%s", (ctype) args[index].data.datatype[j], \
  426.                   j < args[index-1].data.d_int32 - 1 ? ", " : ""); \
  427.     } \
  428.   else \
  429.     trace_printf (__("(UNINITIALIZED)")); \
  430.   trace_printf ("]"); \
  431. }
  432.  
  433. static void
  434. dump_params (int nparams, GimpParam *args, GimpParamDef *params)
  435. {
  436.   static char *ptype[GIMP_PDB_END+1] = {
  437.     "INT32"      , "INT16"      , "INT8"      , "FLOAT"      , "STRING"     ,
  438.     "INT32ARRAY" , "INT16ARRAY" , "INT8ARRAY" , "FLOATARRAY" , "STRINGARRAY",
  439.     "COLOR"      , "REGION"     , "DISPLAY"   , "IMAGE"      , "LAYER"      ,
  440.     "CHANNEL"    , "DRAWABLE"   , "SELECTION" , "BOUNDARY"   , "PATH"       ,
  441. #if GIMP_PARASITE
  442.     "PARASITE"   ,
  443. #endif
  444.     "STATUS"     , "END"
  445.   };
  446.   int i;
  447.   
  448.   trace_printf ("(");
  449.   
  450.   if ((trace & TRACE_DESC) == TRACE_DESC)
  451.     trace_printf ("\n\t");
  452.   
  453.   for (i = 0; i < nparams; i++)
  454.     {
  455.       if ((trace & TRACE_TYPE) == TRACE_TYPE)
  456.         {
  457.       if ((unsigned int)params[i].type < GIMP_PDB_END+1)
  458.         trace_printf ("%s ", ptype[params[i].type]);
  459.       else
  460.         trace_printf ("T%d ", params[i].type);
  461.         }
  462.       
  463.       if ((trace & TRACE_NAME) == TRACE_NAME)
  464.     trace_printf ("%s=", params[i].name);
  465.       
  466.       switch (args[i].type)
  467.     {
  468.       case GIMP_PDB_INT32:        trace_printf ("%d", args[i].data.d_int32); break;
  469.       case GIMP_PDB_INT16:        trace_printf ("%d", args[i].data.d_int16); break;
  470.       case GIMP_PDB_INT8:        trace_printf ("%d", (guint8) args[i].data.d_int8); break;
  471.       case GIMP_PDB_FLOAT:        trace_printf ("%f", args[i].data.d_float); break;
  472.           case GIMP_PDB_STRING:        trace_printf ("\"%s\"", args[i].data.d_string ? args[i].data.d_string : "[null]"); break;
  473.       case GIMP_PDB_DISPLAY:    trace_printf ("%d", args[i].data.d_display); break;
  474.       case GIMP_PDB_IMAGE:        trace_printf ("%d", args[i].data.d_image); break;
  475.       case GIMP_PDB_LAYER:        trace_printf ("%d", args[i].data.d_layer); break;
  476.       case GIMP_PDB_CHANNEL:    trace_printf ("%d", args[i].data.d_channel); break;
  477.       case GIMP_PDB_DRAWABLE:    trace_printf ("%d", args[i].data.d_drawable); break;
  478.       case GIMP_PDB_SELECTION:    trace_printf ("%d", args[i].data.d_selection); break;
  479.       case GIMP_PDB_BOUNDARY:    trace_printf ("%d", args[i].data.d_boundary); break;
  480.       case GIMP_PDB_PATH:        trace_printf ("%d", args[i].data.d_path); break;
  481.       case GIMP_PDB_STATUS:        trace_printf ("%d", args[i].data.d_status); break;
  482.       case GIMP_PDB_INT32ARRAY:    dump_printarray (args, i, gint32, d_int32array, "%d"); break;
  483.       case GIMP_PDB_INT16ARRAY:    dump_printarray (args, i, gint16, d_int16array, "%d"); break;
  484.       case GIMP_PDB_INT8ARRAY:    dump_printarray (args, i, guint8, d_int8array , "%d"); break;
  485.       case GIMP_PDB_FLOATARRAY:    dump_printarray (args, i, gfloat, d_floatarray, "%f"); break;
  486.       case GIMP_PDB_STRINGARRAY:    dump_printarray (args, i, char* , d_stringarray, "'%s'"); break;
  487.       
  488.       case GIMP_PDB_COLOR:
  489.         trace_printf ("[%d,%d,%d]",
  490.                       args[i].data.d_color.red,
  491.                       args[i].data.d_color.green,
  492.                       args[i].data.d_color.blue);
  493.         break;
  494.  
  495. #if GIMP_PARASITE
  496.       case GIMP_PDB_PARASITE:
  497.         {
  498.           gint32 found = 0;
  499.  
  500.               if (args[i].data.d_parasite.name)
  501.                 {
  502.                  trace_printf ("[%s, ", args[i].data.d_parasite.name);
  503.                  if (args[i].data.d_parasite.flags & GIMP_PARASITE_PERSISTENT)
  504.                    {
  505.                      trace_printf ("GIMP_PARASITE_PERSISTENT");
  506.                      found |= GIMP_PARASITE_PERSISTENT;
  507.                    }
  508.                  
  509.                  if (args[i].data.d_parasite.flags & ~found)
  510.                    {
  511.                      if (found)
  512.                        trace_printf ("|");
  513.                      trace_printf ("%d", args[i].data.d_parasite.flags & ~found);
  514.                    }
  515.                  
  516.                  trace_printf (__(", %d bytes data]"), args[i].data.d_parasite.size);
  517.                }
  518.               else
  519.                 trace_printf (__("[undefined]"));
  520.         }
  521.         break;
  522. #endif
  523.         
  524.       default:
  525.         trace_printf ("(?%d?)", args[i].type);
  526.     }
  527.       
  528.       if ((trace & TRACE_DESC) == TRACE_DESC)
  529.     trace_printf ("\t\"%s\"\n\t", params[i].description);
  530.       else if (i < nparams - 1)
  531.     trace_printf (", ");
  532.       
  533.     }
  534.   
  535.   trace_printf (")");
  536. }
  537.  
  538. static int
  539. convert_array2paramdef (AV *av, GimpParamDef **res)
  540. {
  541.   int count = 0;
  542.   GimpParamDef *def = 0;
  543.   
  544.   if (av_len (av) >= 0)
  545.     for(;;)
  546.       {
  547.     int idx;
  548.     
  549.     for (idx = 0; idx <= av_len (av); idx++)
  550.       {
  551.         SV *sv = *av_fetch (av, idx, 0);
  552.         SV *type = 0;
  553.         SV *name = 0;
  554.         SV *help = 0;
  555.  
  556.         if (SvROK (sv) && SvTYPE (SvRV (sv)) == SVt_PVAV)
  557.           {
  558.             AV *av = (AV *)SvRV(sv);
  559.             SV **x;
  560.             
  561.             if ((x = av_fetch (av, 0, 0))) type = *x;
  562.             if ((x = av_fetch (av, 1, 0))) name = *x;
  563.             if ((x = av_fetch (av, 2, 0))) help = *x;
  564.           }
  565.         else if (SvIOK(sv))
  566.           type = sv;
  567.  
  568.         if (type)
  569.           {
  570.             if (def)
  571.               {
  572.                 if (is_array (SvIV (type)))
  573.                   {
  574.                     def->type = GIMP_PDB_INT32;
  575.                     def->name = "array_size";
  576.                     def->description = "the size of the following array";
  577.                     def++;
  578.                   }
  579.                 
  580.                 def->type = SvIV (type);
  581.                 def->name = name ? SvPV_nolen (name) : 0;
  582.                 def->description = help ? SvPV_nolen (help) : 0;
  583.                 def++;
  584.               }
  585.             else
  586.               count += 1 + !!is_array (SvIV (type));
  587.           }
  588.         else
  589.           croak (__("malformed paramdef, expected [PARAM_TYPE,\"NAME\",\"DESCRIPTION\"] or PARAM_TYPE"));
  590.       }
  591.     
  592.     if (def)
  593.       break;
  594.     
  595.     *res = def = g_new (GimpParamDef, count);
  596.       }
  597.   else
  598.     *res = 0;
  599.   
  600.   return count;
  601. }
  602.  
  603. static SV *
  604. newSV_paramdefs (GimpParamDef *p, int n)
  605. {
  606.    int i;
  607.    AV *av = newAV ();
  608.  
  609.    av_extend (av, n-1);
  610.    for (i=0; i<n; i++)
  611.      {
  612.        AV *a = newAV ();
  613.        av_extend (a, 3-1);
  614.        av_store (a, 0, newSViv (p->type));
  615.        av_store (a, 1, newSVpv (p->name,0));
  616.        av_store (a, 2, newSVpv (p->description,0));
  617.        p++;
  618.  
  619.        av_store (av, i, newRV_noinc ((SV*)a));
  620.      }
  621.  
  622.    return newRV_noinc ((SV*)av);
  623. }
  624.  
  625. static HV *
  626. param_stash (GimpPDBArgType type)
  627. {
  628.   static HV *bless_hv[GIMP_PDB_END]; /* initialized to zero */
  629.   static char *bless[GIMP_PDB_END] = {
  630.                         0        , 0        , 0        , 0        , 0        ,
  631.                         0        , 0        , 0        , 0        , 0        ,
  632.                         PKG_COLOR    , PKG_REGION    , PKG_DISPLAY    , PKG_IMAGE    , PKG_LAYER    ,
  633.                         PKG_CHANNEL    , PKG_DRAWABLE    , PKG_SELECTION    , 0        , 0        ,
  634. #if GIMP_PARASITE
  635.                         PKG_PARASITE,
  636. #endif
  637.                         0
  638.                        };
  639.   
  640.   if (bless [type] && !bless_hv [type])
  641.     bless_hv [type] = gv_stashpv (bless [type], 1);
  642.   
  643.   return bless_hv [type];
  644. }
  645.   
  646. /* automatically bless SV into PARAM_type.  */
  647. /* for what it's worth, we cache the stashes.  */
  648. static SV *
  649. autobless (SV *sv, int type)
  650. {
  651.   HV *stash = param_stash (type);
  652.   
  653.   if (stash)
  654.     sv = sv_bless (newRV_noinc (sv), stash);
  655.  
  656.   if (stash && !SvOBJECT(SvRV(sv)))
  657.     croak ("jupp\n");
  658.   
  659.   return sv;
  660. }
  661.  
  662. /* return gint32 from object, wether iv or rv.  */
  663. static gint32
  664. unbless (SV *sv, char *type, char *croak_str)
  665. {
  666.   if (sv_isobject (sv))
  667.     if (type == PKG_ANY
  668.     || (type == PKG_ANYABLE && (sv_derived_from (sv, PKG_DRAWABLE)
  669.                                 || sv_derived_from (sv, PKG_LAYER)
  670.                                 || sv_derived_from (sv, PKG_CHANNEL)))
  671.     || sv_derived_from (sv, type))
  672.       {
  673.     if (SvTYPE (SvRV (sv)) == SVt_PVMG)
  674.       return SvIV (SvRV (sv));
  675.     else
  676.       strcpy (croak_str, __("only blessed scalars accepted here"));
  677.       }
  678.     else
  679.       sprintf (croak_str, __("argument type %s expected (not %s)"), type, HvNAME(SvSTASH(SvRV(sv))));
  680.   else
  681.     return SvIV (sv);
  682.   
  683.   return -1;
  684. }
  685.  
  686. static gint32
  687. unbless_croak (SV *sv, char *type)
  688. {
  689.    char croak_str[MAX_STRING];
  690.    gint32 r;
  691.    croak_str[0] = 0;
  692.  
  693.    r = unbless (sv, type, croak_str);
  694.  
  695.    if (croak_str [0])
  696.       croak (croak_str);
  697.    
  698.    return r;
  699. }
  700.  
  701. static void
  702. canonicalize_colour (char *err, SV *sv, GimpParamColor *c)
  703. {
  704.   dSP;
  705.   
  706.   ENTER;
  707.   SAVETMPS;
  708.   
  709.   PUSHMARK(SP);
  710.   XPUSHs (sv);
  711.   PUTBACK;
  712.   
  713.   if (perl_call_pv ("Gimp::canonicalize_colour", G_SCALAR) != 1)
  714.     croak (__("FATAL: canonicalize_colour did not return a value!"));
  715.   
  716.   SPAGAIN;
  717.   
  718.   sv = POPs;
  719.   if (SvROK(sv))
  720.     {
  721.       if (SvTYPE(SvRV(sv)) == SVt_PVAV)
  722.     {
  723.       AV *av = (AV *)SvRV(sv);
  724.       if (av_len(av) == 2)
  725.         {
  726.           c->red   = SvIV(*av_fetch(av, 0, 0));
  727.           c->green = SvIV(*av_fetch(av, 1, 0));
  728.           c->blue  = SvIV(*av_fetch(av, 2, 0));
  729.         }
  730.       else
  731.         sprintf (err, __("a color must have three components (array elements)"));
  732.     }
  733.       else
  734.     sprintf (err, __("illegal type for colour specification"));
  735.     }
  736.   else
  737.     sprintf (err, __("unable to grok colour specification"));
  738.   
  739.   PUTBACK;
  740.   FREETMPS;
  741.   LEAVE;
  742. }
  743.  
  744. /* check for common typoes.  */
  745. static void check_for_typoe (char *croak_str, char *p)
  746. {
  747.   char b[80];
  748.  
  749.   g_snprintf (b, sizeof b, "%s_MODE", p);    if (perl_get_cv (b, 0)) goto gotit;
  750.   g_snprintf (b, sizeof b, "%s_MASK", p);    if (perl_get_cv (b, 0)) goto gotit;
  751.   g_snprintf (b, sizeof b, "SELECTION_%s", p);    if (perl_get_cv (b, 0)) goto gotit;
  752.   g_snprintf (b, sizeof b, "%s_IMAGE", p);    if (perl_get_cv (b, 0)) goto gotit;
  753.  
  754.   strcpy (b, "1"); if (strEQ (p, "TRUE" )) goto gotit;
  755.   strcpy (b, "0"); if (strEQ (p, "FALSE")) goto gotit;
  756.   
  757.   return;
  758.  
  759. gotit:
  760.   sprintf (croak_str, __("Expected an INT32 but got '%s'. Maybe you meant '%s' instead and forgot to 'use strict'"), p, b);
  761. }
  762.  
  763. /* check for 'enumeration types', i.e. integer constants. do not allow
  764.    string constants here, and check for common typoes. */
  765. static int check_int (char *croak_str, SV *sv)
  766. {
  767.   if (SvTYPE (sv) == SVt_PV && !SvIOKp(sv))
  768.     {
  769.       char *p = SvPV_nolen (sv);
  770.  
  771.       if (*p
  772.           && *p != '0' && *p != '1' && *p != '2' && *p != '3' && *p != '4'
  773.           && *p != '5' && *p != '6' && *p != '7' && *p != '8' && *p != '9'
  774.           && *p != '-')
  775.         {
  776.           sprintf (croak_str, __("Expected an INT32 but got '%s'. Add '*1' if you really intend to pass in a string"), p);
  777.           check_for_typoe (croak_str, p);
  778.           return 0;
  779.         }
  780.     }
  781.   return 1;
  782. }
  783.  
  784. /* replacement newSVpv with only one argument.  */
  785. #define neuSVpv(arg) ((arg) ? newSVpv((arg),0) : newSVsv (&PL_sv_undef))
  786.  
  787. /* replacement newSViv which casts to unsigned char.  */
  788. #define newSVu8(arg) newSViv((unsigned char)(arg))
  789.  
  790. /* create sv's using newsv, from the array arg.  */
  791. #define push_gimp_av(arg,datatype,newsv,as_ref) {        \
  792.   int j;                            \
  793.   AV *av;                            \
  794.   if (as_ref)                            \
  795.     av = newAV ();                        \
  796.   else                                \
  797.     { av = 0; EXTEND (SP, arg[-1].data.d_int32); }        \
  798.   for (j = 0; j < arg[-1].data.d_int32; j++)            \
  799.     if (as_ref)                            \
  800.       av_push (av, newsv (arg->data.datatype[j]));        \
  801.     else                            \
  802.       PUSHs (sv_2mortal (newsv (arg->data.datatype[j])));    \
  803.   if (as_ref)                            \
  804.     PUSHs (sv_2mortal (newRV_noinc ((SV *)av)));        \
  805. }
  806.  
  807. static void
  808. push_gimp_sv (GimpParam *arg, int array_as_ref)
  809. {
  810.   dSP;
  811.   SV *sv = 0;
  812.   
  813.   switch (arg->type)
  814.     {
  815.       case GIMP_PDB_INT32:        sv = newSViv(arg->data.d_int32    ); break;
  816.       case GIMP_PDB_INT16:        sv = newSViv(arg->data.d_int16    ); break;
  817.       case GIMP_PDB_INT8:        sv = newSVu8(arg->data.d_int8    ); break;
  818.       case GIMP_PDB_FLOAT:        sv = newSVnv(arg->data.d_float    ); break;
  819.       case GIMP_PDB_STRING:    sv = neuSVpv(arg->data.d_string ); break;
  820.     
  821.       case GIMP_PDB_DISPLAY:
  822.       case GIMP_PDB_IMAGE:    
  823.       case GIMP_PDB_LAYER:    
  824.       case GIMP_PDB_CHANNEL:
  825.       case GIMP_PDB_DRAWABLE:
  826.       case GIMP_PDB_SELECTION:
  827.       case GIMP_PDB_BOUNDARY:
  828.       case GIMP_PDB_PATH:    
  829.       case GIMP_PDB_STATUS:
  830.          
  831.         {
  832.           int id;
  833.  
  834.           switch (arg->type) {
  835.             case GIMP_PDB_DISPLAY:        id = arg->data.d_display; break;
  836.             case GIMP_PDB_IMAGE:        id = arg->data.d_image; break;
  837.             case GIMP_PDB_LAYER:        id = arg->data.d_layer; break;
  838.             case GIMP_PDB_CHANNEL:        id = arg->data.d_channel; break;
  839.             case GIMP_PDB_DRAWABLE:    id = arg->data.d_drawable; break;
  840.             case GIMP_PDB_SELECTION:    id = arg->data.d_selection; break;
  841.             case GIMP_PDB_BOUNDARY:    id = arg->data.d_boundary; break;
  842.             case GIMP_PDB_PATH:        id = arg->data.d_path; break;
  843.             case GIMP_PDB_STATUS:        id = arg->data.d_status; break;
  844.             default:            abort ();
  845.           }
  846.  
  847.           if (id == -1)
  848.             PUSHs (newSVsv (&PL_sv_undef));
  849.           else
  850.             sv = newSViv (id);
  851.         }
  852.         break;
  853.  
  854.       case GIMP_PDB_COLOR:
  855.     {
  856.       /* difficult */
  857.       AV *av = newAV ();
  858.       av_push (av, newSViv (arg->data.d_color.red));
  859.       av_push (av, newSViv (arg->data.d_color.green));
  860.       av_push (av, newSViv (arg->data.d_color.blue));
  861.       sv = (SV *)av; /* no newRV_inc, since we're getting autoblessed! */
  862.     }
  863.     break;
  864.  
  865. #if GIMP_PARASITE
  866.       case GIMP_PDB_PARASITE:
  867.         if (arg->data.d_parasite.name)
  868.           {
  869.             AV *av = newAV ();
  870.             av_push (av, neuSVpv (arg->data.d_parasite.name));
  871.             av_push (av, newSViv (arg->data.d_parasite.flags));
  872.             av_push (av, newSVpv (arg->data.d_parasite.data, arg->data.d_parasite.size));
  873.             sv = (SV *)av;
  874.           }
  875.  
  876.     break;
  877. #endif
  878.       
  879.       /* did I say difficult before????  */
  880.       case GIMP_PDB_INT32ARRAY:    push_gimp_av (arg, d_int32array , newSViv, array_as_ref); break;
  881.       case GIMP_PDB_INT16ARRAY:    push_gimp_av (arg, d_int16array , newSViv, array_as_ref); break;
  882.       case GIMP_PDB_INT8ARRAY:    push_gimp_av (arg, d_int8array  , newSVu8, array_as_ref); break;
  883.       case GIMP_PDB_FLOATARRAY:    push_gimp_av (arg, d_floatarray , newSVnv, array_as_ref); break;
  884.       case GIMP_PDB_STRINGARRAY:    push_gimp_av (arg, d_stringarray, neuSVpv, array_as_ref); break;
  885.     
  886.       default:
  887.     croak (__("dunno how to return param type %d"), arg->type);
  888.     }
  889.   
  890.   if (sv)
  891.     PUSHs (sv_2mortal (autobless (sv, arg->type)));
  892.   
  893.   PUTBACK;
  894. }
  895.  
  896. #define SvPv(sv) (SvOK(sv) ? SvPV_nolen(sv) : 0)
  897. #define Sv32(sv) unbless ((sv), PKG_ANY, croak_str)
  898.  
  899. #define av2gimp(arg,sv,datatype,type,svxv) { \
  900.   if (SvROK (sv) && SvTYPE(SvRV(sv)) == SVt_PVAV) \
  901.     { \
  902.       int i; \
  903.       AV *av = (AV *)SvRV(sv); \
  904.       arg[-1].data.d_int32 = av_len (av) + 1; \
  905.       arg->data.datatype = g_new (type, av_len (av) + 1); \
  906.       for (i = 0; i <= av_len (av); i++) \
  907.     arg->data.datatype[i] = svxv (*av_fetch (av, i, 0)); \
  908.     } \
  909.   else \
  910.     { \
  911.       sprintf (croak_str, __("perl-arrayref required as datatype for a gimp-array")); \
  912.       arg->data.datatype = 0; \
  913.     } \
  914. }
  915.  
  916. #define sv2gimp_extract_noref(fun,str) \
  917.     fun(sv); \
  918.     if (SvROK(sv)) \
  919.       sprintf (croak_str, __("Unable to convert a reference to type '%s'"), str); \
  920.           break;
  921. /*
  922.  * convert a perl scalar into a GimpParam, return true if
  923.  * the argument has been consumed.
  924.  */
  925. static int
  926. convert_sv2gimp (char *croak_str, GimpParam *arg, SV *sv)
  927. {
  928.   switch (arg->type)
  929.     {
  930.       case GIMP_PDB_INT32:        check_int (croak_str, sv);
  931.                          arg->data.d_int32    = sv2gimp_extract_noref (SvIV, "INT32");
  932.       case GIMP_PDB_INT16:        arg->data.d_int16    = sv2gimp_extract_noref (SvIV, "INT16");
  933.       case GIMP_PDB_INT8:        arg->data.d_int8    = sv2gimp_extract_noref (SvIV, "INT8");
  934.       case GIMP_PDB_FLOAT:        arg->data.d_float    = sv2gimp_extract_noref (SvNV, "FLOAT");
  935.       case GIMP_PDB_STRING:        arg->data.d_string    = sv2gimp_extract_noref (SvPv, "STRING");
  936.  
  937.       case GIMP_PDB_DISPLAY:
  938.       case GIMP_PDB_IMAGE:    
  939.       case GIMP_PDB_LAYER:    
  940.       case GIMP_PDB_CHANNEL:
  941.       case GIMP_PDB_DRAWABLE:
  942.       case GIMP_PDB_SELECTION:
  943.       case GIMP_PDB_BOUNDARY:
  944.       case GIMP_PDB_PATH:    
  945.       case GIMP_PDB_STATUS:
  946.  
  947.         if (SvOK(sv))
  948.           switch (arg->type) {
  949.             case GIMP_PDB_DISPLAY:    arg->data.d_display    = unbless(sv, PKG_DISPLAY  , croak_str); break;
  950.             case GIMP_PDB_LAYER:    arg->data.d_layer    = unbless(sv, PKG_ANYABLE  , croak_str); break;
  951.             case GIMP_PDB_CHANNEL:    arg->data.d_channel    = unbless(sv, PKG_ANYABLE  , croak_str); break;
  952.             case GIMP_PDB_DRAWABLE:    arg->data.d_drawable    = unbless(sv, PKG_ANYABLE  , croak_str); break;
  953.             case GIMP_PDB_SELECTION:    arg->data.d_selection    = unbless(sv, PKG_SELECTION, croak_str); break;
  954.             case GIMP_PDB_BOUNDARY:    arg->data.d_boundary    = sv2gimp_extract_noref (SvIV, "BOUNDARY"); break;
  955.             case GIMP_PDB_PATH:        arg->data.d_path    = sv2gimp_extract_noref (SvIV, "PATH"); break;
  956.             case GIMP_PDB_STATUS:    arg->data.d_status    = sv2gimp_extract_noref (SvIV, "STATUS"); break;
  957.             case GIMP_PDB_IMAGE:
  958.               {
  959.                 if (sv_derived_from (sv, PKG_DRAWABLE))
  960.                   arg->data.d_image = gimp_drawable_image_id    (unbless(sv, PKG_DRAWABLE, croak_str));
  961.                 else if (sv_derived_from (sv, PKG_LAYER   ))
  962.                   arg->data.d_image = gimp_layer_get_image_id   (unbless(sv, PKG_LAYER   , croak_str));
  963.                 else if (sv_derived_from (sv, PKG_CHANNEL ))
  964.                   arg->data.d_image = gimp_channel_get_image_id (unbless(sv, PKG_CHANNEL , croak_str));
  965.                 else if (sv_derived_from (sv, PKG_IMAGE) || !SvROK (sv))
  966.                   {
  967.                                         arg->data.d_image      = unbless(sv, PKG_IMAGE   , croak_str); break;
  968.                   }
  969.                 else
  970.                   strcpy (croak_str, __("argument incompatible with type IMAGE"));
  971.  
  972.                 return 0;
  973.               }
  974.  
  975.             default:
  976.               abort ();
  977.           }
  978.         else
  979.           switch (arg->type) {
  980.             case GIMP_PDB_DISPLAY:    arg->data.d_display    = -1; break;
  981.             case GIMP_PDB_LAYER:    arg->data.d_layer    = -1; break;
  982.             case GIMP_PDB_CHANNEL:    arg->data.d_channel    = -1; break;
  983.             case GIMP_PDB_DRAWABLE:    arg->data.d_drawable    = -1; break;
  984.             case GIMP_PDB_SELECTION:    arg->data.d_selection    = -1; break;
  985.             case GIMP_PDB_BOUNDARY:    arg->data.d_boundary    = -1; break;
  986.             case GIMP_PDB_PATH:        arg->data.d_path    = -1; break;
  987.             case GIMP_PDB_STATUS:    arg->data.d_status    = -1; break;
  988.             case GIMP_PDB_IMAGE:    arg->data.d_image    = -1; return 0; break;
  989.             default:            abort ();
  990.           }
  991.           
  992.           break;
  993.           
  994.       case GIMP_PDB_COLOR:
  995.     canonicalize_colour (croak_str, sv, &arg->data.d_color);
  996.     break;
  997.  
  998. #if GIMP_PARASITE
  999.       case GIMP_PDB_PARASITE:
  1000.     if (SvROK(sv))
  1001.       {
  1002.         if (SvTYPE(SvRV(sv)) == SVt_PVAV)
  1003.           {
  1004.             AV *av = (AV *)SvRV(sv);
  1005.             if (av_len(av) == 2)
  1006.               {
  1007.                     STRLEN size;
  1008.  
  1009.                 arg->data.d_parasite.name  = SvPv(*av_fetch(av, 0, 0));
  1010.                 arg->data.d_parasite.flags = SvIV(*av_fetch(av, 1, 0));
  1011.                 arg->data.d_parasite.data  = SvPV(*av_fetch(av, 2, 0), size);
  1012.  
  1013.                     arg->data.d_parasite.size = size;
  1014.               }
  1015.             else
  1016.               sprintf (croak_str, __("illegal parasite specification, expected three array members"));
  1017.           }
  1018.         else
  1019.           sprintf (croak_str, __("illegal parasite specification, arrayref expected"));
  1020.       }
  1021.     else
  1022.       sprintf (croak_str, __("illegal parasite specification, reference expected"));
  1023.     
  1024.     break;
  1025. #endif
  1026.       
  1027.       case GIMP_PDB_INT32ARRAY:    av2gimp (arg, sv, d_int32array , gint32 , Sv32); break;
  1028.       case GIMP_PDB_INT16ARRAY:    av2gimp (arg, sv, d_int16array , gint16 , SvIV); break;
  1029.       case GIMP_PDB_INT8ARRAY:    av2gimp (arg, sv, d_int8array  , gint8  , SvIV); break;
  1030.       case GIMP_PDB_FLOATARRAY:    av2gimp (arg, sv, d_floatarray , gdouble, SvNV); break;
  1031.       case GIMP_PDB_STRINGARRAY:    av2gimp (arg, sv, d_stringarray, gchar *, SvPv); break;
  1032.     
  1033.       default:
  1034.     sprintf (croak_str, __("dunno how to pass arg type %d"), arg->type);
  1035.     }
  1036.   
  1037.   return 1;
  1038. }
  1039.  
  1040. /* do not free actual string or parasite data */
  1041. static void
  1042. destroy_params (GimpParam *arg, int count)
  1043. {
  1044.   int i;
  1045.   
  1046.   for (i = 0; i < count; i++)
  1047.     switch (arg[i].type)
  1048.       {
  1049.     case GIMP_PDB_INT32ARRAY:    g_free (arg[i].data.d_int32array); break;
  1050.     case GIMP_PDB_INT16ARRAY:    g_free (arg[i].data.d_int16array); break;
  1051.     case GIMP_PDB_INT8ARRAY:    g_free (arg[i].data.d_int8array); break;
  1052.     case GIMP_PDB_FLOATARRAY:    g_free (arg[i].data.d_floatarray); break;
  1053.     case GIMP_PDB_STRINGARRAY:    g_free (arg[i].data.d_stringarray); break;
  1054.       
  1055.     default: ;
  1056.       }
  1057.   
  1058.   g_free (arg);
  1059. }
  1060.  
  1061. #ifdef GIMP_HAVE_DESTROY_PARAMDEFS
  1062. #define destroy_paramdefs gimp_destroy_paramdefs
  1063. #else
  1064. static void
  1065. destroy_paramdefs (GimpParamDef *arg, int count)
  1066. {
  1067.   int i;
  1068.   
  1069.   for (i = 0; i < count; i++)
  1070.     {
  1071.       g_free (arg[i].name);
  1072.       g_free (arg[i].description);
  1073.     }
  1074.   
  1075.   g_free (arg);
  1076. }
  1077. #endif
  1078.  
  1079. #ifdef GIMP_HAVE_PROCEDURAL_DB_GET_DATA_SIZE
  1080. #define get_data_size gimp_get_data_size
  1081. #else
  1082. static guint32
  1083. get_data_size (gchar *id)
  1084. {
  1085.   GimpParam *return_vals;
  1086.   int nreturn_vals;
  1087.   int length;
  1088.  
  1089.   return_vals = gimp_run_procedure ("gimp_procedural_db_get_data",
  1090.                                     &nreturn_vals,
  1091.                                     GIMP_PDB_STRING, id,
  1092.                                     GIMP_PDB_END);
  1093.  
  1094.   if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
  1095.     length = return_vals[1].data.d_int32;
  1096.   else
  1097.     length = 0;
  1098.  
  1099.   gimp_destroy_params (return_vals, nreturn_vals);
  1100.  
  1101.   return length;
  1102. }
  1103. #endif
  1104.  
  1105. static void simple_perl_call (char *function, char *arg1)
  1106. {
  1107.    dSP;
  1108.  
  1109.    ENTER;
  1110.    SAVETMPS;
  1111.  
  1112.    PUSHMARK (SP);
  1113.    XPUSHs (sv_2mortal (newSVpv (arg1, 0)));
  1114.  
  1115.    PUTBACK;
  1116.    perl_call_pv (function, G_VOID);
  1117.    SPAGAIN;
  1118.  
  1119.    FREETMPS;
  1120.    LEAVE;
  1121. }
  1122.  
  1123. #define gimp_die_msg(msg) simple_perl_call ("Gimp::die_msg" , (msg))
  1124. #define try_call(cb)      simple_perl_call ("Gimp::callback", (cb) )
  1125.  
  1126. static void pii_init (void) { try_call ("-init" ); }
  1127. static void pii_query(void) { try_call ("-query"); }
  1128. static void pii_quit (void) { try_call ("-quit" ); }
  1129.  
  1130. static void pii_run(char *name, int nparams, GimpParam *param, int *xnreturn_vals, GimpParam **xreturn_vals)
  1131. {
  1132.   static GimpParam *return_vals;
  1133.   static int nreturn_vals;
  1134.   
  1135.   dSP;
  1136.  
  1137.   int i, count;
  1138.   char *err_msg = 0;
  1139.   
  1140.   char *proc_blurb;
  1141.   char *proc_help;
  1142.   char *proc_author;
  1143.   char *proc_copyright;
  1144.   char *proc_date;
  1145.   GimpPDBProcType proc_type;
  1146.   int _nparams;
  1147.   GimpParamDef *params;
  1148.   GimpParamDef *return_defs;
  1149.  
  1150.    if (return_vals) /* the libgimp is soooooooo braindamaged. */
  1151.      {
  1152.        destroy_params (return_vals, nreturn_vals);
  1153.        return_vals = 0;
  1154.      }
  1155.  
  1156.   if (gimp_procedural_db_proc_info (name, &proc_blurb, &proc_help, &proc_author,
  1157.                        &proc_copyright, &proc_date, &proc_type, &_nparams, &nreturn_vals,
  1158.                        ¶ms, &return_defs) == TRUE)
  1159.     {
  1160.       g_free (proc_blurb);
  1161.       g_free (proc_help);
  1162.       g_free (proc_author);
  1163.       g_free (proc_copyright);
  1164.       g_free (proc_date);
  1165.       destroy_paramdefs (params, _nparams);
  1166.       
  1167.       PUSHMARK(SP);
  1168.  
  1169.       EXTEND (SP, 3);
  1170.       PUSHs (sv_2mortal (newSVpv ("-run", 4)));
  1171.       PUSHs (sv_2mortal (newSVpv (name, 0)));
  1172.       
  1173.       if (nparams)
  1174.     {
  1175.       EXTEND (SP, perl_param_count (param, nparams));
  1176.       PUTBACK;
  1177.       for (i = 0; i < nparams; i++)
  1178.         {
  1179.           if (i < nparams-1 && is_array (param[i+1].type))
  1180.             i++;
  1181.           
  1182.           push_gimp_sv (param+i, nparams > 2);
  1183.         }
  1184.       
  1185.       SPAGAIN;
  1186.     }
  1187.       else
  1188.     PUTBACK;
  1189.       
  1190.       count = perl_call_pv ("Gimp::callback", G_EVAL
  1191.                         | (nreturn_vals == 0 ? G_VOID : nreturn_vals == 1 ? G_SCALAR : G_ARRAY));
  1192.       SPAGAIN;
  1193.       
  1194.       if (SvTRUE (ERRSV))
  1195.     {
  1196.           if (strEQ ("IGNORE THIS MESSAGE\n", SvPV_nolen (ERRSV)))
  1197.             {
  1198.               nreturn_vals = 0;
  1199.               return_vals = g_new (GimpParam, 1);
  1200.               return_vals->type = GIMP_PDB_STATUS;
  1201.               return_vals->data.d_status = GIMP_PDB_SUCCESS;
  1202.               *xnreturn_vals = nreturn_vals+1;
  1203.               *xreturn_vals = return_vals;
  1204.             }
  1205.           else
  1206.             err_msg = g_strdup (SvPV_nolen (ERRSV));
  1207.     }
  1208.       else
  1209.     {
  1210.       int i;
  1211.       char errmsg [MAX_STRING];
  1212.       errmsg [0] = 0;
  1213.       
  1214.       return_vals = (GimpParam *) g_new0 (GimpParam, nreturn_vals+1);
  1215.       return_vals->type = GIMP_PDB_STATUS;
  1216.       return_vals->data.d_status = GIMP_PDB_SUCCESS;
  1217.       *xnreturn_vals = nreturn_vals+1;
  1218.       *xreturn_vals = return_vals++;
  1219.  
  1220.       for (i = nreturn_vals; i-- && count; )
  1221.          {
  1222.            return_vals[i].type = return_defs[i].type;
  1223.            if ((i >= nreturn_vals-1 || !is_array (return_defs[i+1].type))
  1224.                && convert_sv2gimp (errmsg, &return_vals[i], TOPs))
  1225.              {
  1226.                --count;
  1227.                (void) POPs;
  1228.              }
  1229.            
  1230.            if (errmsg [0])
  1231.              {
  1232.                err_msg = g_strdup (errmsg);
  1233.                break;
  1234.              }
  1235.          }
  1236.       
  1237.       if (count && !err_msg)
  1238.         err_msg = g_strdup_printf (__("plug-in returned %d more values than expected"), count);
  1239.     }
  1240.       
  1241.       destroy_paramdefs (return_defs, nreturn_vals);
  1242.       
  1243.       PUTBACK;
  1244.     }
  1245.   else
  1246.     err_msg = g_strdup_printf (__("being called as '%s', but '%s' not registered in the pdb"), name, name);
  1247.   
  1248.   if (err_msg)
  1249.     {
  1250.       gimp_die_msg (err_msg);
  1251.       g_free (err_msg);
  1252.       
  1253.       if (return_vals)
  1254.     destroy_params (*xreturn_vals, nreturn_vals+1);
  1255.       
  1256.       nreturn_vals = 0;
  1257.       return_vals = g_new (GimpParam, 1);
  1258.       return_vals->type = GIMP_PDB_STATUS;
  1259.       return_vals->data.d_status = GIMP_PDB_EXECUTION_ERROR;
  1260.       *xnreturn_vals = nreturn_vals+1;
  1261.       *xreturn_vals = return_vals;
  1262.     }
  1263. }
  1264.  
  1265. GimpPlugInInfo PLUG_IN_INFO = { pii_init, pii_quit, pii_query, pii_run };
  1266.  
  1267. MODULE = Gimp::Lib    PACKAGE = Gimp::Lib
  1268.  
  1269. PROTOTYPES: ENABLE
  1270.  
  1271. #
  1272. # usage:
  1273. # set_trace (int new_trace_mask);
  1274. # set_trace (\$variable_to_trace_into);
  1275. # set_trace (*STDOUT);
  1276. #
  1277. I32
  1278. set_trace (var)
  1279.     CODE:
  1280.     {
  1281.         SV *sv = ST (0);
  1282.         
  1283.         RETVAL = trace;
  1284.         
  1285.         if (SvROK (sv) || SvTYPE (sv) == SVt_PVGV)
  1286.           {
  1287.                 if (trace_var)
  1288.               SvREFCNT_dec (trace_var), trace_var = 0;
  1289.             
  1290.             if (SvTYPE (sv) == SVt_PVGV) /* pray it's a filehandle!  */
  1291.               trace_file = IoOFP (GvIO (sv));
  1292.             else
  1293.               {
  1294.                 trace_file = 0;
  1295.                 sv = SvRV (sv);
  1296.                 SvREFCNT_inc (sv);
  1297.                 (void) SvUPGRADE (sv, SVt_PV);
  1298.                 trace_var = sv;
  1299.               }
  1300.           }
  1301.         else
  1302.           trace = SvIV (ST (0));
  1303.     }
  1304.     OUTPUT:
  1305.     RETVAL
  1306.  
  1307. SV *
  1308. _autobless (sv,type)
  1309.     SV *    sv
  1310.     gint32    type
  1311.     CODE:
  1312.     RETVAL = autobless (newSVsv (sv), type);
  1313.     OUTPUT:
  1314.     RETVAL
  1315.  
  1316. PROTOTYPES: DISABLE
  1317.  
  1318. int
  1319. gimp_main(...)
  1320.     PREINIT:
  1321.     CODE:
  1322.         SV *sv;
  1323.         
  1324.         if ((sv = perl_get_sv ("Gimp::help", FALSE)) && SvTRUE (sv))
  1325.           RETVAL = 0;
  1326.         else
  1327.           {
  1328.             char *argv [10];
  1329.             int argc = 0;
  1330.             
  1331.             if (items == 0)
  1332.               {
  1333.                 AV *av = perl_get_av ("ARGV", FALSE);
  1334.                 
  1335.                 argv [argc++] = SvPV_nolen (perl_get_sv ("0", FALSE));
  1336.                 if (av && av_len (av) < 10-1)
  1337.                   {
  1338.                     while (argc-1 <= av_len (av))
  1339.                       argv [argc] = SvPV_nolen (*av_fetch (av, argc-1, 0)),
  1340.                       argc++;
  1341.                   }
  1342.                 else
  1343.                   croak ("internal error (please report): too many arguments to main");
  1344.               }
  1345.             else
  1346.               croak (__("arguments to main not yet supported!"));
  1347.             
  1348.                 gimp_is_initialized = 1;
  1349.             RETVAL = gimp_main (argc, argv);
  1350.                 gimp_is_initialized = 0;
  1351.                     /*exit (0);*/ /*D*//* shit, some memory problem here, so just exit */
  1352.           }
  1353.     OUTPUT:
  1354.     RETVAL
  1355.  
  1356. PROTOTYPES: ENABLE
  1357.  
  1358. int
  1359. initialized()
  1360.     CODE:
  1361.     RETVAL = gimp_is_initialized;
  1362.     OUTPUT:
  1363.     RETVAL
  1364.  
  1365. int
  1366. gimp_major_version()
  1367.        CODE:
  1368.     RETVAL = gimp_major_version;
  1369.     OUTPUT:
  1370.     RETVAL
  1371.  
  1372. int
  1373. gimp_minor_version()
  1374.        CODE:
  1375.     RETVAL = gimp_minor_version;
  1376.     OUTPUT:
  1377.     RETVAL
  1378.  
  1379. int
  1380. gimp_micro_version()
  1381.        CODE:
  1382.     RETVAL = gimp_micro_version;
  1383.     OUTPUT:
  1384.     RETVAL
  1385.  
  1386. # checks wether a gimp procedure exists
  1387. int
  1388. _gimp_procedure_available(proc_name)
  1389.     char * proc_name
  1390.     CODE:
  1391.     {
  1392.         char *proc_blurb;    
  1393.         char *proc_help;
  1394.         char *proc_author;
  1395.         char *proc_copyright;
  1396.         char *proc_date;
  1397.         GimpPDBProcType proc_type;
  1398.         int nparams;
  1399.         int nreturn_vals;
  1400.         GimpParamDef *params;
  1401.         GimpParamDef *return_vals;
  1402.  
  1403.                 if (!gimp_is_initialized)
  1404.                   croak ("_gimp_procedure_available(%s) called without an active connection", proc_name);
  1405.         
  1406.         if (gimp_procedural_db_proc_info (proc_name, &proc_blurb, &proc_help, &proc_author,
  1407.             &proc_copyright, &proc_date, &proc_type, &nparams, &nreturn_vals,
  1408.             ¶ms, &return_vals) == TRUE)
  1409.           {
  1410.             g_free (proc_blurb);
  1411.             g_free (proc_help);
  1412.             g_free (proc_author);
  1413.             g_free (proc_copyright);
  1414.             g_free (proc_date);
  1415.             destroy_paramdefs (params, nparams);
  1416.             destroy_paramdefs (return_vals, nreturn_vals);
  1417.             RETVAL = TRUE;
  1418.           }
  1419.         else
  1420.           RETVAL = FALSE;
  1421.             
  1422.     }
  1423.     OUTPUT:
  1424.     RETVAL
  1425.  
  1426. #if 0
  1427.  
  1428. # checks wether a gimp procedure exists
  1429. void
  1430. gimp_procedural_db_proc_info(proc_name)
  1431.     char * proc_name
  1432.     PPCODE:
  1433.     {
  1434.         char *proc_blurb;    
  1435.         char *proc_help;
  1436.         char *proc_author;
  1437.         char *proc_copyright;
  1438.         char *proc_date;
  1439.         GimpPDBProcType proc_type;
  1440.         int nparams;
  1441.         int nreturn_vals;
  1442.         GimpParamDef *params;
  1443.         GimpParamDef *return_vals;
  1444.         
  1445.                 if (!gimp_is_initialized)
  1446.                   croak ("gimp_procedural_db_proc_info called without an active connection");
  1447.  
  1448.         if (gimp_procedural_db_proc_info (proc_name, &proc_blurb, &proc_help, &proc_author,
  1449.             &proc_copyright, &proc_date, &proc_type, &nparams, &nreturn_vals,
  1450.             ¶ms, &return_vals) == TRUE)
  1451.           {
  1452.                     EXTEND (SP,8);
  1453.                     PUSHs (newSVpv (proc_blurb,0));    g_free (proc_blurb);
  1454.             PUSHs (newSVpv (proc_help,0));    g_free (proc_help);
  1455.             PUSHs (newSVpv (proc_author,0));    g_free (proc_author);
  1456.             PUSHs (newSVpv (proc_copyright,0));    g_free (proc_copyright);
  1457.             PUSHs (newSVpv (proc_date,0));    g_free (proc_date);
  1458.             PUSHs (newSViv (proc_type));
  1459.                     PUSHs (newSV_paramdefs (params, nparams));        destroy_paramdefs (params, nparams);
  1460.             PUSHs (newSV_paramdefs (return_vals, nreturn_vals));destroy_paramdefs (return_vals, nreturn_vals);
  1461.           }
  1462.     }
  1463.  
  1464. #endif
  1465.  
  1466. void
  1467. gimp_call_procedure (proc_name, ...)
  1468.     char *    proc_name
  1469.     PPCODE:
  1470.     {
  1471.         char croak_str[MAX_STRING] = "";
  1472.         char *proc_blurb;    
  1473.         char *proc_help;
  1474.         char *proc_author;
  1475.         char *proc_copyright;
  1476.         char *proc_date;
  1477.         GimpPDBProcType proc_type;
  1478.         int nparams;
  1479.         int nreturn_vals;
  1480.         GimpParam *args = 0;
  1481.         GimpParam *values = 0;
  1482.         int nvalues;
  1483.         GimpParamDef *params;
  1484.         GimpParamDef *return_vals;
  1485.                 int i=0, j=0; /* work around bogus warning.  */
  1486.  
  1487.                 if (!gimp_is_initialized)
  1488.                   croak ("gimp_call_procedure(%s,...) called without an active connection", proc_name);
  1489.  
  1490.         if (trace)
  1491.           trace_init ();
  1492.         
  1493.         if (trace & TRACE_CALL)
  1494.           trace_printf ("%s", proc_name);
  1495.         
  1496.         if (gimp_procedural_db_proc_info (proc_name, &proc_blurb, &proc_help, &proc_author,
  1497.             &proc_copyright, &proc_date, &proc_type, &nparams, &nreturn_vals,
  1498.             ¶ms, &return_vals) == TRUE)
  1499.           {
  1500.             int runmode = nparams
  1501.                           && params[0].type == GIMP_PDB_INT32
  1502.                           && !strcmp (params[0].name, "run_mode");
  1503.             
  1504.             g_free (proc_blurb);
  1505.             g_free (proc_help);
  1506.             g_free (proc_author);
  1507.             g_free (proc_copyright);
  1508.             g_free (proc_date);
  1509.             
  1510.                     if (nparams)
  1511.                       args = (GimpParam *) g_new0 (GimpParam, nparams);
  1512.  
  1513.                     for (i = 0, j = 1; i < nparams && j < items; i++)
  1514.                       {
  1515.                         args[i].type = params[i].type;
  1516.                         if (i == 0 && runmode)
  1517.                            {
  1518.                              if (sv_isa (ST(j), "Gimp::run_mode"))
  1519.                                {
  1520.                                  args->data.d_int32 = SvIV(SvRV(ST(j)));
  1521.                                  j++;
  1522.                                }
  1523.                              else
  1524.                                args->data.d_int32 = GIMP_RUN_NONINTERACTIVE;
  1525.                            }
  1526.                         else if ((!SvROK(ST(j)) || i >= nparams-1 || !is_array (params[i+1].type))
  1527.                                  && convert_sv2gimp (croak_str, &args[i], ST(j)))
  1528.                           j++;
  1529.                     
  1530.                         if (croak_str [0])
  1531.                           {
  1532.                             if (trace & TRACE_CALL)
  1533.                               {
  1534.                                 dump_params (i, args, params);
  1535.                                 trace_printf (__(" = [argument error]\n"));
  1536.                               }
  1537.                         
  1538.                             goto error;
  1539.                           }
  1540.                       }
  1541.                   
  1542.                     if (trace & TRACE_CALL)
  1543.                       {
  1544.                         dump_params (i, args, params);
  1545.                         trace_printf (" = ");
  1546.                       }
  1547.                     
  1548.                     if (i < nparams || j < items)
  1549.                       {
  1550.                         if (trace & TRACE_CALL)
  1551.                           trace_printf (__("[unfinished]\n"));
  1552.                         
  1553.                         sprintf (croak_str, __("%s arguments for function '%s'"),
  1554.                                  i < nparams ? __("not enough") : __("too many"), proc_name);
  1555.                         
  1556.                         if (nparams)
  1557.                           destroy_params (args, nparams);
  1558.                       }
  1559.                     else
  1560.                       {
  1561.                         values = gimp_run_procedure2 (proc_name, &nvalues, nparams, args);
  1562.                         
  1563.                         if (nparams)
  1564.                           destroy_params (args, nparams);
  1565.                     
  1566.                         if (trace & TRACE_CALL)
  1567.                           {
  1568.                             dump_params (nvalues-1, values+1, return_vals);
  1569.                             trace_printf ("\n");
  1570.                           }
  1571.                         
  1572.                         if (values && values[0].type == GIMP_PDB_STATUS)
  1573.                           {
  1574.                             if (values[0].data.d_status == GIMP_PDB_EXECUTION_ERROR)
  1575.                               sprintf (croak_str, __("%s: procedural database execution failed"), proc_name);
  1576.                             else if (values[0].data.d_status == GIMP_PDB_CALLING_ERROR)
  1577.                               sprintf (croak_str, __("%s: procedural database execution failed on invalid input arguments"), proc_name);
  1578.                             else if (values[0].data.d_status == GIMP_PDB_SUCCESS)
  1579.                               {
  1580.                                 EXTEND(SP, perl_paramdef_count (return_vals, nvalues-1));
  1581.                                 PUTBACK;
  1582.                                 for (i = 0; i < nvalues-1; i++)
  1583.                                   {
  1584.                                     if (i < nvalues-2 && is_array (values[i+2].type))
  1585.                                       i++;
  1586.                                     
  1587.                                     push_gimp_sv (values+i+1, nvalues > 2+1);
  1588.                                   }
  1589.                                 
  1590.                                 SPAGAIN;
  1591.                               }
  1592.                             else
  1593.                               sprintf (croak_str, "unsupported status code: %d, fatal error\n", values[0].data.d_status);
  1594.                           }
  1595.                         else
  1596.                           sprintf (croak_str, "gimp didn't return an execution status, fatal error");
  1597.                         
  1598.                       }
  1599.                     
  1600.                     error:
  1601.  
  1602.                     if (values)
  1603.                       gimp_destroy_params (values, nreturn_vals);
  1604.                     
  1605.                     destroy_paramdefs (params, nparams);
  1606.                     destroy_paramdefs (return_vals, nreturn_vals);
  1607.                     
  1608.         
  1609.                     if (croak_str[0])
  1610.                       croak (croak_str);
  1611.                   }
  1612.                 else
  1613.                   croak (__("gimp procedure '%s' not found"), proc_name);
  1614.     }
  1615.  
  1616. void
  1617. gimp_install_procedure(name, blurb, help, author, copyright, date, menu_path, image_types, type, params, return_vals)
  1618.     char *    name
  1619.     char *    blurb
  1620.     char *    help
  1621.     char *    author
  1622.     char *    copyright
  1623.     char *    date
  1624.     SV *    menu_path
  1625.     SV *    image_types
  1626.     int    type
  1627.     SV *    params
  1628.     SV *    return_vals
  1629.     ALIAS:
  1630.         gimp_install_temp_proc = 1
  1631.     CODE:
  1632.         if (SvROK(params) && SvTYPE(SvRV(params)) == SVt_PVAV
  1633.             && SvROK(return_vals) && SvTYPE(SvRV(return_vals)) == SVt_PVAV)
  1634.           {
  1635.             GimpParamDef *apd; int nparams;
  1636.             GimpParamDef *rpd; int nreturn_vals;
  1637.             
  1638.             nparams      = convert_array2paramdef ((AV *)SvRV(params)     , &apd);
  1639.             nreturn_vals = convert_array2paramdef ((AV *)SvRV(return_vals), &rpd);
  1640.             
  1641.             if (ix)
  1642.               gimp_install_temp_proc(name,blurb,help,author,copyright,date,SvPv(menu_path),SvPv(image_types),
  1643.                                      type,nparams,nreturn_vals,apd,rpd,pii_run);
  1644.             else
  1645.               {
  1646.             gimp_plugin_domain_register ("gimp-perl", datadir "/locale");
  1647.  
  1648.                 gimp_install_procedure(name,blurb,help,author,copyright,date,SvPv(menu_path),SvPv(image_types),
  1649.                                        type,nparams,nreturn_vals,apd,rpd);
  1650.               }
  1651.             
  1652.             g_free (rpd);
  1653.             g_free (apd);
  1654.           }
  1655.         else
  1656.           croak (__("params and return_vals must be array refs (even if empty)!"));
  1657.  
  1658. void
  1659. gimp_uninstall_temp_proc(name)
  1660.     char *    name
  1661.  
  1662. void
  1663. gimp_lib_quit()
  1664.     CODE:
  1665.     gimp_quit ();
  1666.  
  1667. void
  1668. gimp_set_data(id, data)
  1669.     SV *    id
  1670.     SV *    data;
  1671.     CODE:
  1672.     {
  1673.         STRLEN dlen;
  1674.         void *dta;
  1675.         
  1676.         dta = SvPV (data, dlen);
  1677.  
  1678.         gimp_set_data (SvPV_nolen (id), dta, dlen);
  1679.     }
  1680.  
  1681. void
  1682. gimp_get_data(id)
  1683.     SV *    id;
  1684.     PPCODE:
  1685.     {
  1686.         SV *data;
  1687.         STRLEN dlen;
  1688.         
  1689.         dlen = get_data_size (SvPV_nolen (id));
  1690.         /* I count on dlen being zero if "id" doesn't exist.  */
  1691.         data = newSVpv ("", 0);
  1692.         gimp_get_data (SvPV_nolen (id), SvGROW (data, dlen+1));
  1693.         SvCUR_set (data, dlen);
  1694.         *((char *)SvPV_nolen (data) + dlen) = 0;
  1695.             XPUSHs (sv_2mortal (data));
  1696.     }
  1697.  
  1698. gdouble
  1699. gimp_gamma()
  1700.  
  1701. gint
  1702. gimp_install_cmap()
  1703.  
  1704. gint
  1705. gimp_use_xshm()
  1706.  
  1707. void
  1708. gimp_color_cube()
  1709.     PPCODE:
  1710.     {
  1711.          guchar *cc = gimp_color_cube ();
  1712.  
  1713.         EXTEND (SP, 4);
  1714.  
  1715.         PUSHs (sv_2mortal (newSViv (cc [0])));
  1716.         PUSHs (sv_2mortal (newSViv (cc [1])));
  1717.         PUSHs (sv_2mortal (newSViv (cc [2])));
  1718.         PUSHs (sv_2mortal (newSViv (cc [3])));
  1719.     }
  1720.     
  1721.  
  1722. char *
  1723. gimp_gtkrc()
  1724.  
  1725. #ifdef GIMP11
  1726. char *
  1727. gimp_directory()
  1728.  
  1729. char *
  1730. gimp_data_directory()
  1731.  
  1732. SV *
  1733. gimp_personal_rc_file(basename)
  1734.     char *    basename
  1735.     CODE:
  1736.         basename = gimp_personal_rc_file (basename);
  1737.         RETVAL = sv_2mortal (newSVpv (basename, 0));
  1738.         g_free (basename);
  1739.         OUTPUT:
  1740.         RETVAL
  1741.  
  1742. #endif
  1743.  
  1744. guint
  1745. gimp_tile_width()
  1746.  
  1747. guint
  1748. gimp_tile_height()
  1749.  
  1750. void
  1751. gimp_tile_cache_size(kilobytes)
  1752.     gulong    kilobytes
  1753.  
  1754. void
  1755. gimp_tile_cache_ntiles(ntiles)
  1756.     gulong    ntiles
  1757.  
  1758. SV *
  1759. gimp_drawable_get(drawable_ID)
  1760.     DRAWABLE    drawable_ID
  1761.     CODE:
  1762.         RETVAL = new_gdrawable (drawable_ID);
  1763.     OUTPUT:
  1764.     RETVAL
  1765.  
  1766. void
  1767. gimp_drawable_flush(drawable)
  1768.     GimpDrawable *    drawable
  1769.  
  1770. SV *
  1771. gimp_pixel_rgn_init(gdrawable, x, y, width, height, dirty, shadow)
  1772.     SV *    gdrawable
  1773.     int    x
  1774.     int    y
  1775.     int    width
  1776.     int    height
  1777.     int    dirty
  1778.     int    shadow
  1779.     CODE:
  1780.         RETVAL = new_gpixelrgn (force_gdrawable (gdrawable),x,y,width,height,dirty,shadow);
  1781.     OUTPUT:
  1782.     RETVAL
  1783.  
  1784. void
  1785. gimp_pixel_rgn_resize(pr, x, y, width, height)
  1786.     GimpPixelRgn *    pr
  1787.     int    x
  1788.     int    y
  1789.     int    width
  1790.     int    height
  1791.     CODE:
  1792.     gimp_pixel_rgn_resize (pr, x, y, width, height);
  1793.  
  1794. GimpPixelRgnIterator
  1795. gimp_pixel_rgns_register(...)
  1796.     CODE:
  1797.         if (items == 1)
  1798.       RETVAL = gimp_pixel_rgns_register (1, old_pixelrgn (ST (0)));
  1799.         else if (items == 2)
  1800.       RETVAL = gimp_pixel_rgns_register (2, old_pixelrgn (ST (0)), old_pixelrgn (ST (1)));
  1801.         else if (items == 3)
  1802.       RETVAL = gimp_pixel_rgns_register (3, old_pixelrgn (ST (0)), old_pixelrgn (ST (1)), old_pixelrgn (ST (2)));
  1803.         else
  1804.           croak (__("gimp_pixel_rgns_register supports only 1, 2 or 3 arguments, upgrade to gimp-1.1 and report this error"));
  1805.         OUTPUT:
  1806.         RETVAL
  1807.  
  1808. SV *
  1809. gimp_pixel_rgns_process(pri_ptr)
  1810.     GimpPixelRgnIterator    pri_ptr
  1811.         CODE:
  1812.         RETVAL = boolSV (gimp_pixel_rgns_process (pri_ptr));
  1813.         OUTPUT:
  1814.         RETVAL
  1815.  
  1816. # struct accessor functions
  1817.  
  1818. guint
  1819. gimp_gdrawable_width(gdrawable)
  1820.     GimpDrawable *gdrawable
  1821.     CODE:
  1822.         RETVAL = gdrawable->width;
  1823.     OUTPUT:
  1824.     RETVAL
  1825.  
  1826. guint
  1827. gimp_gdrawable_height(gdrawable)
  1828.     GimpDrawable *gdrawable
  1829.     CODE:
  1830.         RETVAL = gdrawable->height;
  1831.     OUTPUT:
  1832.     RETVAL
  1833.  
  1834. guint
  1835. gimp_gdrawable_ntile_rows(gdrawable)
  1836.     GimpDrawable *gdrawable
  1837.     CODE:
  1838.         RETVAL = gdrawable->ntile_rows;
  1839.     OUTPUT:
  1840.     RETVAL
  1841.  
  1842. guint
  1843. gimp_gdrawable_ntile_cols(gdrawable)
  1844.     GimpDrawable *gdrawable
  1845.     CODE:
  1846.         RETVAL = gdrawable->ntile_cols;
  1847.     OUTPUT:
  1848.     RETVAL
  1849.  
  1850. guint
  1851. gimp_gdrawable_bpp(gdrawable)
  1852.     GimpDrawable *gdrawable
  1853.     CODE:
  1854.         RETVAL = gdrawable->bpp;
  1855.     OUTPUT:
  1856.     RETVAL
  1857.  
  1858. gint32
  1859. gimp_gdrawable_id(gdrawable)
  1860.     GimpDrawable *gdrawable
  1861.     CODE:
  1862.         RETVAL = gdrawable->id;
  1863.     OUTPUT:
  1864.     RETVAL
  1865.  
  1866. guint
  1867. gimp_pixel_rgn_x(pr)
  1868.     GimpPixelRgn *pr
  1869.     CODE:
  1870.         RETVAL = pr->x;
  1871.     OUTPUT:
  1872.     RETVAL
  1873.  
  1874. guint
  1875. gimp_pixel_rgn_y(pr)
  1876.     GimpPixelRgn *pr
  1877.     CODE:
  1878.         RETVAL = pr->y;
  1879.     OUTPUT:
  1880.     RETVAL
  1881.  
  1882. guint
  1883. gimp_pixel_rgn_w(pr)
  1884.     GimpPixelRgn *pr
  1885.     CODE:
  1886.         RETVAL = pr->w;
  1887.     OUTPUT:
  1888.     RETVAL
  1889.  
  1890. guint
  1891. gimp_pixel_rgn_h(pr)
  1892.     GimpPixelRgn *pr
  1893.     CODE:
  1894.         RETVAL = pr->h;
  1895.     OUTPUT:
  1896.     RETVAL
  1897.  
  1898. guint
  1899. gimp_pixel_rgn_rowstride(pr)
  1900.     GimpPixelRgn *pr
  1901.     CODE:
  1902.         RETVAL = pr->rowstride;
  1903.     OUTPUT:
  1904.     RETVAL
  1905.  
  1906. guint
  1907. gimp_pixel_rgn_bpp(pr)
  1908.     GimpPixelRgn *pr
  1909.     CODE:
  1910.         RETVAL = pr->bpp;
  1911.     OUTPUT:
  1912.     RETVAL
  1913.  
  1914. guint
  1915. gimp_pixel_rgn_shadow(pr)
  1916.     GimpPixelRgn *pr
  1917.     CODE:
  1918.         RETVAL = pr->shadow;
  1919.     OUTPUT:
  1920.     RETVAL
  1921.  
  1922. gint32
  1923. gimp_pixel_rgn_drawable(pr)
  1924.     GimpPixelRgn *pr
  1925.     CODE:
  1926.         RETVAL = pr->drawable->id;
  1927.     OUTPUT:
  1928.     RETVAL
  1929.  
  1930. guint
  1931. gimp_tile_ewidth(tile)
  1932.     GimpTile *tile
  1933.     CODE:
  1934.         RETVAL = tile->ewidth;
  1935.     OUTPUT:
  1936.     RETVAL
  1937.  
  1938. guint
  1939. gimp_tile_eheight(tile)
  1940.     GimpTile *tile
  1941.     CODE:
  1942.         RETVAL = tile->eheight;
  1943.     OUTPUT:
  1944.     RETVAL
  1945.  
  1946. guint
  1947. gimp_tile_bpp(tile)
  1948.     GimpTile *tile
  1949.     CODE:
  1950.         RETVAL = tile->bpp;
  1951.     OUTPUT:
  1952.     RETVAL
  1953.  
  1954. guint
  1955. gimp_tile_shadow(tile)
  1956.     GimpTile *tile
  1957.     CODE:
  1958.         RETVAL = tile->shadow;
  1959.     OUTPUT:
  1960.     RETVAL
  1961.  
  1962. guint
  1963. gimp_tile_dirty(tile)
  1964.     GimpTile *tile
  1965.     CODE:
  1966.         RETVAL = tile->dirty;
  1967.     OUTPUT:
  1968.     RETVAL
  1969.  
  1970. DRAWABLE
  1971. gimp_tile_drawable(tile)
  1972.     GimpTile *tile
  1973.     CODE:
  1974.         RETVAL = tile->drawable->id;
  1975.     OUTPUT:
  1976.     RETVAL
  1977.  
  1978. SV *
  1979. gimp_pixel_rgn_get_row2(pr, x, y, width)
  1980.     GimpPixelRgn *    pr
  1981.     int    x
  1982.     int    y
  1983.     int    width
  1984.     CODE:
  1985.         RETVAL = newSVn (width * pr->bpp);
  1986.     gimp_pixel_rgn_get_row (pr, (guchar *)SvPV_nolen(RETVAL), x, y, width);
  1987.     OUTPUT:
  1988.     RETVAL
  1989.  
  1990. SV *
  1991. gimp_pixel_rgn_get_rect2(pr, x, y, width, height)
  1992.     GimpPixelRgn *    pr
  1993.     int    x
  1994.     int    y
  1995.     int    width
  1996.     int    height
  1997.     CODE:
  1998.         RETVAL = newSVn (width * height * pr->bpp);
  1999.     gimp_pixel_rgn_get_rect (pr, (guchar *)SvPV_nolen(RETVAL), x, y, width, height);
  2000.     OUTPUT:
  2001.     RETVAL
  2002.  
  2003. void
  2004. gimp_pixel_rgn_set_rect2(pr, data, x, y, w=pr->w)
  2005.     GimpPixelRgn *    pr
  2006.     SV *    data
  2007.     int    x
  2008.     int    y
  2009.         int    w
  2010.     CODE:
  2011. {
  2012.         STRLEN dlen; guchar *dta = (guchar *)SvPV (data, dlen);
  2013.     gimp_pixel_rgn_set_rect (pr, dta, x, y, w, dlen / (w*pr->bpp));
  2014. }
  2015.  
  2016. #if HAVE_PDL
  2017.  
  2018. SV *
  2019. gimp_drawable_get_tile(gdrawable, shadow, row, col)
  2020.     SV *    gdrawable
  2021.     gint    shadow
  2022.     gint    row
  2023.     gint    col
  2024.     CODE:
  2025.         need_pdl ();
  2026.     RETVAL = new_tile (gimp_drawable_get_tile (old_gdrawable (gdrawable), shadow, row, col), gdrawable);
  2027.     OUTPUT:
  2028.     RETVAL
  2029.  
  2030. SV *
  2031. gimp_drawable_get_tile2(gdrawable, shadow, x, y)
  2032.     SV *    gdrawable
  2033.     gint    shadow
  2034.     gint    x
  2035.     gint    y
  2036.     CODE:
  2037.         need_pdl ();
  2038.     RETVAL = new_tile (gimp_drawable_get_tile2 (old_gdrawable (gdrawable), shadow, x, y), gdrawable);
  2039.     OUTPUT:
  2040.     RETVAL
  2041.  
  2042. pdl *
  2043. gimp_pixel_rgn_get_pixel(pr, x, y)
  2044.     GimpPixelRgn_PDL *    pr
  2045.     int    x
  2046.     int    y
  2047.     CODE:
  2048.         RETVAL = new_pdl (0, 0, pr->bpp);
  2049.     gimp_pixel_rgn_get_pixel (pr, RETVAL->data, x, y);
  2050.     OUTPUT:
  2051.     RETVAL
  2052.  
  2053. pdl *
  2054. gimp_pixel_rgn_get_row(pr, x, y, width)
  2055.     GimpPixelRgn_PDL *    pr
  2056.     int    x
  2057.     int    y
  2058.     int    width
  2059.     CODE:
  2060.         RETVAL = new_pdl (0, width, pr->bpp);
  2061.     gimp_pixel_rgn_get_row (pr, RETVAL->data, x, y, width);
  2062.     OUTPUT:
  2063.     RETVAL
  2064.  
  2065. pdl *
  2066. gimp_pixel_rgn_get_col(pr, x, y, height)
  2067.     GimpPixelRgn_PDL *    pr
  2068.     int    x
  2069.     int    y
  2070.     int    height
  2071.     CODE:
  2072.         RETVAL = new_pdl (height, 0, pr->bpp);
  2073.     gimp_pixel_rgn_get_col (pr, RETVAL->data, x, y, height);
  2074.     OUTPUT:
  2075.     RETVAL
  2076.  
  2077. pdl *
  2078. gimp_pixel_rgn_get_rect(pr, x, y, width, height)
  2079.     GimpPixelRgn_PDL *    pr
  2080.     int    x
  2081.     int    y
  2082.     int    width
  2083.     int    height
  2084.     CODE:
  2085.         RETVAL = new_pdl (height, width, pr->bpp);
  2086.     gimp_pixel_rgn_get_rect (pr, RETVAL->data, x, y, width, height);
  2087.     OUTPUT:
  2088.     RETVAL
  2089.  
  2090. void
  2091. gimp_pixel_rgn_set_pixel(pr, pdl, x, y)
  2092.     GimpPixelRgn_PDL *    pr
  2093.     pdl *    pdl
  2094.     int    x
  2095.     int    y
  2096.     CODE:
  2097.         old_pdl (&pdl, 0, pr->bpp);
  2098.     gimp_pixel_rgn_set_pixel (pr, pdl->data, x, y);
  2099.  
  2100. void
  2101. gimp_pixel_rgn_set_row(pr, pdl, x, y)
  2102.     GimpPixelRgn_PDL *    pr
  2103.     pdl *    pdl
  2104.     int    x
  2105.     int    y
  2106.     CODE:
  2107.         old_pdl (&pdl, 1, pr->bpp);
  2108.     gimp_pixel_rgn_set_row (pr, pdl->data, x, y, pdl->dims[pdl->ndims-1]);
  2109.  
  2110. void
  2111. gimp_pixel_rgn_set_col(pr, pdl, x, y)
  2112.     GimpPixelRgn_PDL *    pr
  2113.     pdl *    pdl
  2114.     int    x
  2115.     int    y
  2116.     CODE:
  2117.         old_pdl (&pdl, 1, pr->bpp);
  2118.     gimp_pixel_rgn_set_col (pr, pdl->data, x, y, pdl->dims[pdl->ndims-1]);
  2119.  
  2120. void
  2121. gimp_pixel_rgn_set_rect(pr, pdl, x, y)
  2122.     GimpPixelRgn_PDL *    pr
  2123.     pdl *    pdl
  2124.     int    x
  2125.     int    y
  2126.     CODE:
  2127.         old_pdl (&pdl, 2, pr->bpp);
  2128.     gimp_pixel_rgn_set_rect (pr, pdl->data, x, y, pdl->dims[pdl->ndims-2], pdl->dims[pdl->ndims-1]);
  2129.  
  2130. pdl *
  2131. gimp_pixel_rgn_data(pr,newdata=0)
  2132.     GimpPixelRgn_PDL *    pr
  2133.         pdl * newdata
  2134.     CODE:
  2135.         if (newdata)
  2136.       {
  2137.             guchar *src;
  2138.             guchar *dst;
  2139.             int y, stride;
  2140.  
  2141.             old_pdl (&newdata, 2, pr->bpp);
  2142.             stride = pr->bpp * newdata->dims[newdata->ndims-2];
  2143.  
  2144.             if ((int)pr->h != newdata->dims[newdata->ndims-1])
  2145.               croak (__("pdl height != region height"));
  2146.  
  2147.             for (y   = 0, src = newdata->data, dst = pr->data;
  2148.                  y < (int)pr->h;
  2149.                  y++    , src += stride      , dst += pr->rowstride)
  2150.               Copy (src, dst, stride, char);
  2151.  
  2152.             RETVAL = newdata;
  2153.           }
  2154.         else
  2155.           {
  2156.             pdl *p = PDL->new();
  2157.             PDL_Long dims[3];
  2158.  
  2159.             dims[0] = pr->bpp;
  2160.             dims[1] = pr->rowstride / pr->bpp;
  2161.             dims[2] = pr->h;
  2162.  
  2163.             PDL->setdims (p, dims, 3);
  2164.             p->datatype = PDL_B;
  2165.             p->data = pr->data;
  2166.             p->state |= PDL_DONTTOUCHDATA | PDL_ALLOCATED;
  2167.             PDL->add_deletedata_magic(p, pixel_rgn_pdl_delete_data, 0);
  2168.  
  2169.             if ((int)pr->w != dims[1])
  2170.               p = redim_pdl (p, 1, pr->w);
  2171.  
  2172.             RETVAL = p;
  2173.           }
  2174.     OUTPUT:
  2175.     RETVAL
  2176.  
  2177. # ??? optimize these two functions so tile_*ref will only be called once on
  2178. # construction/destruction.
  2179.  
  2180. SV *
  2181. gimp_tile_get_data(tile)
  2182.     GimpTile *    tile
  2183.     CODE:
  2184.         need_pdl ();
  2185.         croak (__("gimp_tile_get_data is not yet implemented\n"));
  2186.     gimp_tile_ref (tile);
  2187.     gimp_tile_unref (tile, 0);
  2188.     OUTPUT:
  2189.     RETVAL
  2190.  
  2191. void
  2192. gimp_tile_set_data(tile,data)
  2193.     GimpTile *    tile
  2194.     SV *    data
  2195.     CODE:
  2196.         croak (__("gimp_tile_set_data is not yet implemented\n")); /*(void *)data;*/
  2197.     gimp_tile_ref_zero (tile);
  2198.     gimp_tile_unref (tile, 1);
  2199.  
  2200. #else
  2201.  
  2202. void
  2203. gimp_pixel_rgn_data(...)
  2204.     ALIAS:
  2205.           gimp_drawable_get_tile    = 1
  2206.           gimp_drawable_get_tile2    = 2
  2207.           gimp_pixel_rgn_get_pixel    = 3
  2208.           gimp_pixel_rgn_get_row    = 4
  2209.           gimp_pixel_rgn_get_col    = 5
  2210.           gimp_pixel_rgn_get_rect    = 6
  2211.           gimp_pixel_rgn_set_pixel    = 7
  2212.           gimp_pixel_rgn_set_row    = 8
  2213.           gimp_pixel_rgn_set_col    = 9
  2214.           gimp_pixel_rgn_set_rect    = 10
  2215.           gimp_tile_get_data        = 11
  2216.           gimp_tile_set_data        = 12
  2217.     CODE:
  2218.         croak (__("This module was built without support for PDL."));
  2219.  
  2220. #endif
  2221.  
  2222. BOOT:
  2223.     trace_file = PerlIO_stderr ();
  2224.  
  2225. #
  2226. # this function overrides a pdb function for speed
  2227. #
  2228.  
  2229. void
  2230. gimp_patterns_get_pattern_data(name)
  2231.     SV *    name
  2232.     PPCODE:
  2233.     {
  2234.         GimpParam *return_vals;
  2235.         int nreturn_vals;
  2236.         
  2237.         return_vals = gimp_run_procedure ("gimp_patterns_get_pattern_data",
  2238.                                           &nreturn_vals,
  2239.                                           GIMP_PDB_STRING, SvPV_nolen (name),
  2240.                                           GIMP_PDB_END);
  2241.         
  2242.         if (nreturn_vals == 7
  2243.             && return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
  2244.           {
  2245.             EXTEND (SP, 5);
  2246.             
  2247.             PUSHs (sv_2mortal (newSVpv (        return_vals[1].data.d_string, 0)));
  2248.             PUSHs (sv_2mortal (newSViv (        return_vals[2].data.d_int32)));
  2249.             PUSHs (sv_2mortal (newSViv (        return_vals[3].data.d_int32)));
  2250.             PUSHs (sv_2mortal (newSViv (        return_vals[4].data.d_int32)));
  2251.             PUSHs (sv_2mortal (newSVpvn((char *)return_vals[6].data.d_int8array, return_vals[5].data.d_int32)));
  2252.           }
  2253.         
  2254.         gimp_destroy_params (return_vals, nreturn_vals);
  2255.     }
  2256.  
  2257. void
  2258. _gimp_progress_init (message)
  2259.     gchar *    message
  2260.         CODE:
  2261.         gimp_progress_init (message);
  2262.  
  2263. #ifdef GIMP_HAVE_DEFAULT_DISPLAY
  2264.  
  2265. DISPLAY
  2266. gimp_default_display()
  2267.  
  2268. #endif
  2269.  
  2270. # functions using different calling conventions:
  2271. #void
  2272. #gimp_channel_get_color(channel_ID, red, green, blue)
  2273. #    CHANNEL    channel_ID
  2274. #    guchar *    red
  2275. #    guchar *    green
  2276. #    guchar *    blue
  2277. #gint32 *
  2278. #gimp_image_get_channels(image_ID, nchannels)
  2279. #    IMAGE    image_ID
  2280. #    gint *    nchannels
  2281. #guchar *
  2282. #gimp_image_get_cmap(image_ID, ncolors)
  2283. #    IMAGE    image_ID
  2284. #    gint *    ncolors
  2285. #gint32 *
  2286. #gimp_image_get_layers(image_ID, nlayers)
  2287. #    IMAGE    image_ID
  2288. #    gint *    nlayers
  2289. #gint32
  2290. #gimp_layer_new(image_ID, name, width, height, type, opacity, mode)
  2291. #    gint32    image_ID
  2292. #    char *    name
  2293. #    guint    width
  2294. #    guint    height
  2295. #    GimpImageType    type
  2296. #    gdouble    opacity
  2297. #    GimpLayerModeEffects    mode
  2298. #gint32
  2299. #gimp_layer_copy(layer_ID)
  2300. #    gint32    layer_ID
  2301. #void
  2302. #gimp_channel_set_color(channel_ID, red, green, blue)
  2303. #    gint32    channel_ID
  2304. #    guchar    red
  2305. #    guchar    green
  2306. #    guchar    blue
  2307. #gint
  2308. #gimp_drawable_mask_bounds(drawable_ID, x1, y1, x2, y2)
  2309. #    DRAWABLE    drawable_ID
  2310. #    gint *    x1
  2311. #    gint *    y1
  2312. #    gint *    x2
  2313. #    gint *    y2
  2314. #void
  2315. #gimp_drawable_offsets(drawable_ID, offset_x, offset_y)
  2316. #    DRAWABLE    drawable_ID
  2317. #    gint *    offset_x
  2318. #    gint *    offset_y
  2319.  
  2320. # ??? almost synonymous to gimp_list_images
  2321.  
  2322. #gint32 *
  2323. #gimp_image_list(nimages)
  2324. #    int *    nimages
  2325.  
  2326.